﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

using Xeno.Module;
using OpenTK.Math;
namespace Xeno.Core
{

    public class XenoImport
    {
    
        public static XenoNode ImportObj(string path, string name,XenoNode parent,Vector3 importScale)
        {

            XenoNode root = new XenoNode(name, parent);
            //XenoMesh mesh = root.Mesh;
            XenoNode aNode = null;
            XenoMesh aMesh = null;

            

            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
            TextReader tr = new StreamReader(fs);

            string[] deli = new string[4];
            deli[0] = " ";
            deli[1] = "\n";
            deli[2] = "\r";
            deli[3] = "\nv";

            List<Vector3> Vertices = new List<Vector3>();
            List<Vector3> Normals = new List<Vector3>();
            List<Vector3> Tex = new List<Vector3>();
            int nIndex=0;
            int tIndex = 0;

            string[] deli2 = new string[3];
            deli2[0] = "/";
            deli2[1] = "\n";
            deli2[2] = "\r";
            bool firstVert = true;
            int NodeIndex = 0;
            while (fs.Position < fs.Length)
            {

                string code = tr.ReadToEnd();

                string[] toks = code.Split(deli, StringSplitOptions.RemoveEmptyEntries);



                for(int i=0;i<toks.Length;i++)
                {
                    string t = toks[i];
                    bool skip = false;
                    switch (t.ToLower())
                    {
                        case "mtllib":
                            
                            break;
                        case "v":
                            if (firstVert)
                            {
                                aNode = XenoFactory.Node.Mesh(name + "_" + NodeIndex, root);
                                aMesh = aNode.Mesh;
                                firstVert = false;
                             
                                NodeIndex++;
                            }
                            Vector3 vec = GetVec3(toks, i);

                            vec.Scale(ref importScale);
                        
                            Vertices.Add(vec);

                        

                           

                            break;
                        case "vn":

                            Vector3 vec2 = GetVec3(toks, i);

                            Normals.Add(vec2);
                           
                            

                            break;
                        case "vt":

                            
                            float u = float.Parse(toks[i + 1]);
                            float v = float.Parse(toks[i + 2]);

                            Tex.Add(new Vector3(u, v, 0));

                         

                            break;

                        case "f":

                         
                            firstVert = true;
                            int cC = 0;
                            string[] cCod = new string[255];

                            for (int k = i+1; k < toks.Length; k++)
                            {
                                bool skip3 = false;
                                string code2 = toks[k];
                                switch (code2.ToLower())
                                {
                                    case "v":
                                    case "f":
                                    case "vn":
                                    case "vt":
                                        skip3 = true;
                                        break;

                                }
                                if(skip3) break;
                                cCod[cC] = code2;
                                cC++;
                            }

                            if (cC == 3)
                            {
                                int index3=0;
                                  int iVert, iNorm, iTex;
                                iVert = iNorm = iTex = 0;
                                if (iNorm < 1)
                                {
                                    iNorm = 1;
                                }
                                Vector3 v1, v2, v3;
                                Vector3 n1, n2, n3;
                                Vector3 t1, t2, t3;

                                n1 = n2 = n3 = Vector3.Zero;
                                t1 = t2 = t3 = Vector3.Zero;
                                ProcComp(cCod,0, ref iVert, ref iNorm, ref iTex);

                                v1 = Vertices[iVert-1];
                                if (Normals.Count > 0)
                                {

                                    n1 = Normals[iNorm - 1];
                                }
                                if (Tex.Count > 0)
                                {
                                    t1 = Tex[iTex - 1];
                                }

                                ProcComp(cCod, 1, ref iVert, ref iNorm, ref iTex);

                                v2 = Vertices[iVert-1];
                                if (Normals.Count > 0)
                                {
                                    n2 = Normals[iNorm - 1];
                                }
                                if (Tex.Count > 0)
                                {
                                    t2 = Tex[iTex - 1];
                                }
                                ProcComp(cCod, 2, ref iVert, ref iNorm, ref iTex);

                                v3 = Vertices[iVert-1];
                                if (Normals.Count > 0)
                                {
                                    n3 = Normals[iNorm - 1];
                                }
                                if (Tex.Count > 0)
                                {
                                    t3 = Tex[iTex - 1];
                                }

                                int vIndex = aMesh.Vertices.Count;

                                aMesh.AddVertex = new XenoVertex(v1, n1, t1);
                                aMesh.AddVertex = new XenoVertex(v2, n2, t2);
                                aMesh.AddVertex = new XenoVertex(v3, n3, t3);

                                aMesh.AddTri(vIndex, vIndex + 1, vIndex + 2);


                            }
                            else if (cC == 4)
                            {
                                int index = 0;
                                int iVert, iNorm, iTex;
                                iVert = iNorm = iTex = 0;
                                if (iNorm < 1)
                                {
                                    iNorm = 1;
                                }
                                Vector3 v1, v2, v3,v4;
                                Vector3 n1, n2, n3,n4;
                                Vector3 t1, t2, t3,t4;

                                n1 = n2 = n3 = n4 = Vector3.Zero;
                                t1 = t2 = t3 = t4 =  Vector3.Zero;
                                ProcComp(cCod, 0, ref iVert, ref iNorm, ref iTex);

                                v1 = Vertices[iVert - 1];
                                if (Normals.Count > 0)
                                {

                                    n1 = Normals[iNorm - 1];
                                }
                                if (Tex.Count > 0)
                                {
                                    t1 = Tex[iTex - 1];
                                }

                                ProcComp(cCod, 1, ref iVert, ref iNorm, ref iTex);

                                v2 = Vertices[iVert - 1];
                                if (Normals.Count > 0)
                                {
                                    n2 = Normals[iNorm - 1];
                                }
                                if (Tex.Count > 0)
                                {
                                    t2 = Tex[iTex - 1];
                                }
                                ProcComp(cCod, 2, ref iVert, ref iNorm, ref iTex);

                                v3 = Vertices[iVert - 1];
                                if (Normals.Count > 0)
                                {
                                    n3 = Normals[iNorm - 1];
                                }
                                if (Tex.Count > 0)
                                {
                                    t3 = Tex[iTex - 1];
                                }

                                ProcComp(cCod, 3, ref iVert, ref iNorm, ref iTex);

                                v4 = Vertices[iVert - 1];
                                if (Normals.Count > 0)
                                {
                                    n4 = Normals[iNorm - 1];
                                }
                                if (Tex.Count > 0)
                                {
                                    t4 = Tex[iTex - 1];
                                }


                                
                                
                                int vIndex = aMesh.Vertices.Count;

                                aMesh.AddVertex = new XenoVertex(v1, n1, t1);
                                aMesh.AddVertex = new XenoVertex(v2, n2, t2);
                                aMesh.AddVertex = new XenoVertex(v3, n3, t3);
                                aMesh.AddVertex = new XenoVertex(v4, n4, t4);

                                aMesh.AddTri(vIndex, vIndex + 1, vIndex + 2);
                                aMesh.AddTri(vIndex + 2, vIndex + 3, vIndex);
                                aMesh.AddTri(vIndex, vIndex + 2, vIndex + 1);
                                aMesh.AddTri(vIndex + 2, vIndex, vIndex + 3);
                            }

                            break;
                        default:
                      
                            break;
                    }
                    if (skip) break;
                }



            }

            fs.Close();

            tr = null;
            fs = null;

            return root;

        }

        private static void ProcComp(string[] cCod, int index3, ref int iVert, ref int iNorm, ref int iTex)
        {
            string[] deli3 = new string[1];
            deli3[0] = "/";
            string[] cInd = cCod[index3].Split(deli3,StringSplitOptions.RemoveEmptyEntries);


            switch (cInd.Length)
            {
                case 1:
                    iVert = int.Parse(cInd[0]);
                    break;
                case 2:
                    iVert = int.Parse(cInd[0]);
                    iTex = int.Parse(cInd[1]);
                    break;
                case 3:
                    iVert = int.Parse(cInd[0]);
                    if (cInd[1] == "/")
                    {
                        iNorm = int.Parse(cInd[2]);
                    }
                    else
                    {
                        iTex = int.Parse(cInd[1]);
                        iNorm = int.Parse(cInd[2]);
                    }
                    break;


            }
        }

        private static void ProcessSeg(string[] deli2, string seg1, int ci, int[,] co)
        {

            string[] par = seg1.Split(deli2, StringSplitOptions.RemoveEmptyEntries);

            int pos = int.Parse(par[0]);
            int tex = int.Parse(par[1]);
            int norm = int.Parse(par[2]);
            co[ci, 0] = pos;
            co[ci, 1] = tex;
            co[ci, 2] = norm;
        }

     
        private static Vector3 GetVec3(string[] toks, int i)
        {
            float x = float.Parse(toks[i + 1]);
            float y = float.Parse(toks[i + 2]);
            float z = float.Parse(toks[i + 3]);
            Vector3 vec = new Vector3(x, y, z);
            return vec;
        }

    }

}
